import React, { useState } from 'react';
import SparkMD5 from 'spark-md5';
import './index.css'
import { useNavigate } from 'react-router-dom';
import { Toast, NavBar } from 'react-vant';

const CHUNK_SIZE = 1024 * 1024; // 1M

function FileUploadComponent() {
    const navigate = useNavigate();
    const [videoTitle, setVideoTitle] = useState('');
    const [videoInfo, setVideoInfo] = useState('');
    let selectedFile = null;
    let fileHash = ''
    let fileName = ''

    const handleFileChange = async (event) => {
        selectedFile = event
    };

    // 文件分片
    const createChunks = (file) => {
        let cur = 0;
        let chunks = [];
        while (cur < file.size) {
            const blob = file.slice(cur, cur + CHUNK_SIZE);
            chunks.push(blob);
            cur += CHUNK_SIZE;
        }
        return chunks;
    };

    // 计算哈希值
    const calculateHash = async (chunks) => {
        console.log('计算 hash 值开始');
        return new Promise(resolve => {
            const targets = [];
            const spark = new SparkMD5.ArrayBuffer();
            const fileReader = new FileReader();

            chunks.forEach((chunk, index) => {
                if (index === 0 || index === chunks.length - 1) {
                    // 1. 第一个和最后一个切片全部参与计算
                    targets.push(chunk);
                } else {
                    // 2. 中间的切片只计算前面两个字节、中间两个字节、最后两个字节
                    targets.push(chunk.slice(0, 2));
                    targets.push(chunk.slice(CHUNK_SIZE / 2 - 2, CHUNK_SIZE / 2 + 2));
                    targets.push(chunk.slice(CHUNK_SIZE - 2, CHUNK_SIZE));
                }
            });

            fileReader.readAsArrayBuffer(new Blob(targets));
            fileReader.onload = (e) => {
                spark.append(e.target.result);
                resolve(spark.end());
            };
        })
    };

    const mergeRequest = async () => {
        console.log('通知服务器去进行合并文件');
        const response = await fetch('http://127.0.0.1:3000/wh_index/merge', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
            },
            body: JSON.stringify({
                fileHash: fileHash,
                fileName: fileName,
                size: CHUNK_SIZE,
                tid: '672f1842c77a076fbb333c78',
                video_text: videoTitle
            }),
        });
        const resData = await response.json();
        alert('合并成功了！');
        console.log('合并成功了！');
        console.log('图片路径：', `http://127.0.0.1:3000/${resData.test}`);
    };

    const uploadChunks = async (chunk, existChunks) => {

        const data = chunk.map((chunk, index) => {
            return {
                fileHash: fileHash,
                chunkHash: fileHash + '-' + index,
                chunk,
            };
        });

        const formDatas = data
            .filter((item) => !existChunks.includes(item.chunkHash))
            .map((item) => {
                const formData = new FormData();
                formData.append('fileHash', item.fileHash);
                formData.append('chunkHash', item.chunkHash);
                formData.append('chunk', item.chunk);
                return formData;
            });

        const max = 6; // 最大并发请求数
        let index = 0;
        const taskPool = [];
        // console.log(formDatas);
        while (index < formDatas.length) {
            const task = fetch('http://127.0.0.1:3000/wh_index/upload', {
                method: 'POST',
                body: formDatas[index],
            });
            // console.log(formDatas[index]);

            taskPool.splice(taskPool.findIndex((item) => item === task));
            taskPool.push(task);
            if (taskPool.length === max) {
                await Promise.race(taskPool);
            }
            index++;
        }
        await Promise.all(taskPool);
        console.log('上传完成');
        navigate('/Foot/video')

        // 通知服务器去合并文件
        mergeRequest();
    };

    const verify = async () => {
        console.log('校验 hash 值');
        const response = await fetch('http://127.0.0.1:3000/wh_index/verify', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
            },
            body: JSON.stringify({
                fileHash: fileHash,
                fileName: fileName,
            }),
        });
        return response.json();
    };

    const handleUpload = async () => {
        console.log(selectedFile.target.files);
        
        event.preventDefault();
        const files = selectedFile.target.files;
        if (!files) return;

        // 读取文件
        console.log('读取文件');
        const file = files[0];
        fileName = file.name;

        // 文件分片
        const chunks = createChunks(file);
        console.log('文件切片:', chunks);

        // hash 计算
        const hash = await calculateHash(chunks);
        fileHash = hash;
        console.log('hash 值为：', hash);

        // 检验 hash 值
        const data = await verify();
        console.log(data.data.shouldUpload);

        if (!data.data.shouldUpload) {
            alert('秒传：上传成功');
            navigate('/Foot/video')
            return;
        }
        console.log(data.data.existChunks);

        // 上传分片
        uploadChunks(chunks, data.data.existChunks);
    };

    return (
        <div className='wh_publish'>
            <NavBar
                leftText={<span >&lt;&nbsp;返回</span>}
                rightText={<span>下一步</span>}
                onClickLeft={() => navigate(-1)}
                onClickRight={() => Toast('暂无内容')}
            />
            <main>
                <form onSubmit={handleUpload}>
                    <div className='fileDiv'>
                        <div className='div'>
                            <div className="file-upload-container">
                                <label htmlFor="fileInput" className="custom-file-upload-button">+</label>
                                <input type="file" onChange={handleFileChange} id="fileInput" style={{ display: 'none' }} />
                            </div>
                        </div>
                    </div>
                    <div style={{ height: '5rem', }}></div>
                    <div>
                        <input type="text" className='text-input' placeholder='请输入视频标题...' onChange={(e) => setVideoTitle(e.target.value)} />
                    </div>
                    <div>
                        <button className='but' type='submit'>发布</button>
                    </div>

                </form>
            </main>

        </div>
    );
}

export default FileUploadComponent;